﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using CSBackup_Web.Sources.Override;

namespace CSBackup_Web.Sources.ui_Legacy
{
    using Directory = System.IO.Directory;

    public static class frmPrtRcvr
    {

        public static long kByte = 1024;

        /// <summary>
        /// 从备份文件夹读取所有已备份文件的信息
        /// 之所以不在此函数内直接获取当前工程句柄而是改用传参的方式，
        /// 是为了将此函数作为一个纯被动工具函数以方便以后的修改。
        /// 在调用此函数前，curPrj引用的当前工程应该已经经过适当处理
        /// </summary>
        /// <param name="curPrj">当前备份工程引用</param>
        /// <returns>0 -- 成功 ；1 -- 参数错误 ；
        /// 2 -- 备份类型错误 ；3 -- 找不到依赖备份 ；
        /// 4 -- 读取文件信息出错</returns>
        public static int LoadAllBkpedFiles(ProjectInfo curPrj)
        {
            if (null == curPrj)
                return 1;

            if (null == curPrj.SelectedBackup)
                return 1;

            BackupInfo curBkp = curPrj.SelectedBackup;
            string selfPath = curBkp.BkpLocation;
            string diffPath = string.Empty;
            int ret = 0;

            //部分恢复功能不支持和增量有关的备份
            if ((BackupInfo.BACKUP_TYPE_INC == curBkp.BkpType)
                || (BackupInfo.BACKUP_TYPE_DIFINC == curBkp.BkpType))
                return 2;

            if (selfPath[selfPath.Length - 1] != '\\')
                selfPath += "\\";
            //全备份和差分备份的恢复步骤有所区别
            if (BackupInfo.BACKUP_TYPE_FULL == curBkp.BkpType)
            {
                selfPath += BackupInfo.BACKUP_FULL_FOLDER_NAME;
                ret = LoadBkpedFileRcsvly(selfPath, string.Empty, curPrj);
            }
            else if (BackupInfo.BACKUP_TYPE_DIF == curBkp.BkpType)
            {
                selfPath += BackupInfo.BACKUP_FULL_FOLDER_NAME;
                ret = LoadBkpedFileRcsvly(selfPath, string.Empty, curPrj);
                //如果是以数据块为单位的差分备份，还需要加入diff文件
                if (BackupInfo.BACKUP_UNIT_DATA == curBkp.BkpUnit)
                {
                    if (string.Empty == curBkp.BkpDepended)
                        return 3;
                    selfPath = curPrj.FullBkpPath.TrimEnd(new char[] { '\\' });
                    selfPath += "\\" + curBkp.BkpDepended.TrimEnd(new char[] { '\\' });
                    selfPath += "\\" + BackupInfo.BACKUP_FULL_FOLDER_NAME;
                    diffPath = curBkp.BkpLocation.TrimEnd(new char[] { '\\' });
                    diffPath += "\\" + BackupInfo.BACKUP_DIF_FOLDER_NAME;
                    ret |= LoadBkpedFileRcsvly(selfPath, diffPath, curPrj);
                }
            }
            else
            {
                return 2;
            }
            if (ret != 0)
                return 4;
            return 0;
        }

        public static int LoadBkpedFileRcsvly(string selfPath, string diffPath, ProjectInfo curPrj)
        {
            if ((null == selfPath) || (null == diffPath))
                return 1;

            if ((null == curPrj) || (null == curPrj.SelectedBackup)
                || (null == curPrj.SelectedFileList)
                || (null == curPrj.SelectedDirList))
                return 1;

            //统一一下路径格式，都不要以分隔符结尾
            selfPath = selfPath.TrimEnd(new Char[] { '\\' });
            diffPath = diffPath.TrimEnd(new Char[] { '\\' });

            int ret = 0;
            string[] fileWithFullPath = null;
            string[] subDirs = null;
            string dirName = string.Empty;
            string dpCopy = string.Empty;
            string rpCopy = string.Empty;
            FileDetail bkpedFile = null;
            FileInfo target = null;
            //如果是目录，记录，然后先载入其下所有文件，再递归处理子目录
            if (Directory.Exists(selfPath))
            {
                bkpedFile = MakeABkpedFile(selfPath, diffPath);
                if (bkpedFile != null)
                {
                    //目录不用判重
                    curPrj.SelectedDirList.Add(bkpedFile);
                }
                else
                    return 2;
                fileWithFullPath = Directory.GetFiles(selfPath);
                foreach (string file in fileWithFullPath)
                {
                    try
                    {
                        target = new FileInfo(file);
                    }
                    catch (Exception exp)
                    {
                        Debug.WriteLine("LoadBkpedFileRcsvly(): " + exp.Message);
                        return 2;
                    }
                    dpCopy = diffPath + "\\" + target.Name;
                    bkpedFile = MakeABkpedFile(file, dpCopy);
                    if (bkpedFile != null)
                    {
                        //文件需要判重
                        if (!curPrj.SelectedFileList.Contains(bkpedFile))
                            curPrj.SelectedFileList.Add(bkpedFile);
                    }
                    else
                        return 2;
                }
                subDirs = Directory.GetDirectories(selfPath);
                foreach (string dir in subDirs)
                {
                    dirName = dir.TrimEnd(new char[] { '\\' });
                    dirName = dirName.Substring(dirName.LastIndexOf('\\') + 1);
                    dpCopy = diffPath + "\\" + dirName;
                    ret = LoadBkpedFileRcsvly(dir, dpCopy, curPrj);
                    if (ret != 0)
                        return ret;
                }
            }
            else
            {
                //传入此函数的不应该直接是一个文件的路径
                return 1;
            }
            return 0;
        }

        /// <summary>
        /// 构造一个已备份文件的FileDetail实例
        /// </summary>
        /// <param name="selfPath">目标文件的全限定名称（全路径）</param>
        /// <param name="diffPath">diff文件全限定名称</param>
        /// <param name="rcvrPath">恢复到文件的全限定名称</param>
        /// <returns>失败返回null</returns>
        public static FileDetail MakeABkpedFile(string selfPath, string diffPath)
        {
            if ((null == selfPath) || (null == diffPath))
                return null;

            selfPath = selfPath.TrimEnd(new Char[] { '\\' });

            long size = 0;
            long residue = 0;
            FileDetail bkpedFile = new FileDetail();
            FileInfo target = null;

            //如果传入的是目录，则构造一个中间目录的FileInfo实例返回
            if (Directory.Exists(selfPath))
            {
                bkpedFile.FileName = selfPath;
                bkpedFile.DiffName = diffPath;
                bkpedFile.Size = 0;
                bkpedFile.Selected = false;
                return bkpedFile;
            }

            try
            {
                target = new FileInfo(selfPath);
            }
            catch (Exception exp)
            {
                Debug.WriteLine("MakeABkpedFile(): " + exp.Message);
                return null;
            }
            if (!target.Exists)
                return null;
            bkpedFile.FileName = selfPath;
            bkpedFile.DiffName = diffPath;
            size = target.Length / kByte;
            residue = target.Length % kByte;
            if (residue > (kByte / 2))
                ++size;
            bkpedFile.Size = (size > uint.MaxValue) ? uint.MaxValue : (uint)size;
            bkpedFile.Selected = false;
            bkpedFile.CreationTime = target.CreationTime;

            return bkpedFile;
        }

    }
}
